
module uart_9600(
    input clk_50M,
    input reset_n,
    
    input  uart_rxd,                 //UART接收端口
    output uart_txd,                  //UART发送端口
    
    output            uart_rec_req,                //接收一帧数据完成标志信号 上升沿表示接收到
    input             uart_rec_ack,
    output      [7:0] uart_data_out,                 //接收的数据
    input             uart_send_req,                  //发送使能信号
    output            uart_send_ack,
    input       [7:0] uart_data_in ,                 //待发送数据
    input dummy
);


uart_recv_9600 ins_uart_recv_9600(
	.clk_50M (clk_50M),
	.reset_n (reset_n),

	.uart_rxd (uart_rxd),
	
	.uart_rec_req (uart_rec_req),
	.uart_rec_ack (uart_rec_ack),
	.uart_data_out (uart_data_out)
);

uart_send_9600 ins_uart_send_9600(
	.clk_50M (clk_50M),
	.reset_n (reset_n),

	.uart_txd (uart_txd),
	
	.uart_send_req (uart_send_req),
	.uart_send_ack (uart_send_ack),
	.uart_data_in (uart_data_in)
);

endmodule


module uart_recv_9600(
    input clk_50M,
    input reset_n,

    input uart_rxd,//UART接收端口

    output reg       uart_rec_req,//接收一帧数据完成标志信号 上升沿表示接收到
    input            uart_rec_ack,
    output reg [7:0] uart_data_out//接收的数据
  );

//parameter define
//localparam BPS_CNT  = 25;        //2000000 bps  50000000/2000000
//localparam BPS_CNT_HALF  = 12;        //2000000 bps  50000000/2000000

//`ifdef is50M_41M6
//localparam BPS_CNT  = 4340; //9600 bps  41666666/9600
//`else
localparam BPS_CNT  = 5208; //9600 bps  50000000/9600
//`endif
localparam BPS_CNT_HALF  = BPS_CNT/2;


reg uart_rxd_last1;
reg uart_rxd_last2;
reg rx_flag; //接收过程标志信号
reg status;

reg [13-1:0] clk_cnt; //系统时钟计数器

reg [3:0] bitcnt;

reg uart_rec_ack_buff;
//根据接收数据计数器来寄存uart接收端口数据
always @(posedge clk_50M or negedge reset_n) begin 
  if ( !reset_n) begin
    rx_flag <= 0;
    clk_cnt <= 0;
    status <= 0;
    uart_rxd_last1 <= 1;
    uart_rxd_last2 <= 1;
    uart_data_out <= 8'd0;
    uart_rec_req <= 0;
    uart_rec_ack_buff <= 0;
    bitcnt <= 0;
  end else begin
    uart_rxd_last1 <= uart_rxd;
    uart_rxd_last2 <= uart_rxd_last1;
    uart_rec_ack_buff <= uart_rec_ack;
    
    clk_cnt <= clk_cnt + 1'b1;

    if(rx_flag)begin
    
      if(clk_cnt == BPS_CNT) begin
        clk_cnt <= 0;
        bitcnt <= bitcnt+1'b1;
        if(bitcnt==8)begin
          uart_rec_req <= 1;
          rx_flag <= 0;
          bitcnt <= 0;
        end else begin
          uart_data_out <= {uart_rxd_last2, uart_data_out[7:1]};
        end
      end
    
    end else begin
      if(status)begin
        if(clk_cnt==BPS_CNT_HALF)begin
          clk_cnt <= 0;
          status <= 0;
          rx_flag <= 1; //进入接收过程，标志位rx_flag拉高
        end
      end else begin
        if(uart_rxd_last2 && !uart_rxd_last1) begin//检测到起始位
          clk_cnt <= 0;
          status <= 1;
        end
      end
    end
    
    
    if(uart_rec_ack_buff)begin
      uart_rec_req <= 0;
    end
    
  end
end

endmodule
module uart_send_9600(
    input clk_50M,
    input reset_n,
    
    output     uart_txd,//UART发送端口

    input       uart_send_req,//发送使能信号
    output reg  uart_send_ack,
    input [7:0] uart_data_in//待发送数据
  );

//parameter define
//localparam BPS_CNT  = 25; //2000000 bps  50000000/2000000
//localparam BPS_CNT_HALF  = 12;        //2000000 bps  50000000/2000000

//`ifdef is50M_41M6
//localparam BPS_CNT  = 4340; //9600 bps  41666666/9600
//`else
localparam BPS_CNT  = 5208; //9600 bps  50000000/9600
//`endif
localparam BPS_CNT_HALF  = BPS_CNT/2;

reg uart_send_req_buff;
reg [13-1:0] clk_cnt;//系统时钟计数器

reg [3:0] bitcnt;
reg [9:0] senddata;
reg sendStatus;
assign uart_txd = senddata[0];

//根据发送数据计数器来给uart发送端口赋值
always @(posedge clk_50M or negedge reset_n) begin
  if (!reset_n) begin
    clk_cnt <= 0;
    uart_send_req_buff <= 0;
    uart_send_ack <= 0;
    bitcnt<=0;
    senddata<=10'b1;
    sendStatus <= 0;
  end else begin
    uart_send_req_buff <= uart_send_req;
    clk_cnt <= clk_cnt + 1'b1;

    case(sendStatus)
      0: begin
        if(uart_send_req_buff && !uart_send_ack) begin //检测到发送使能上升沿
          bitcnt<=0;
          senddata<={1'b1,uart_data_in,1'b0};
          clk_cnt <= 0;
          sendStatus <= 1;
        end
      end
      
      1: begin
        if(clk_cnt == BPS_CNT)begin
          clk_cnt <= 0;
          if(bitcnt!=11)begin
            bitcnt<=bitcnt+1'b1;
            senddata<={1'b1,senddata[9:1]};
          end else begin
            uart_send_ack <= 1;
            sendStatus <= 0;
          end
        end
      end
      
    endcase
    
    if(!uart_send_req_buff && uart_send_ack) begin
      uart_send_ack <= 0;
    end
  end
end

endmodule

